﻿package net.sealuitk 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.ContextMenuEvent;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import net.sealuitk.containers.Window;
	import net.sealuitk.styles.StyleContainer;
	
	/**
	 * ...
	 * @author mkn
	 */
	public class Container extends Sprite
	{
		protected var size:Point;
		protected var sizeSet:Boolean = false;
		
		protected var contentArea:Rectangle;
		protected var padding:Rectangle = new Rectangle(0, 0, 0, 0);
		protected var contentPadding:Point = new Point(0, 0);
		
		protected var framesLayer:Sprite;
		protected var fixedLayer:Sprite;
		protected var floatingLayer:Sprite;
		
		private var _alignVertical:String;
		private var _alignHorizontal:String;
		
		public var background:*;
		protected var backgroundMode:String = UIConst.GRAPHICS_STRETCH;
		
		public var style:StyleContainer;
		protected var frameMode:String;
		
		protected var hasSides:Boolean = false;
		
		protected var sideTop:Bitmap;
		protected var sideBottom:Bitmap;
		protected var sideLeft:Bitmap;
		protected var sideRight:Bitmap;
		
		protected var hasCorners:Boolean = false;
		
		protected var cornerTopLeft:Bitmap;
		protected var cornerTopRight:Bitmap;
		protected var cornerBottomLeft:Bitmap;
		protected var cornerBottomRight:Bitmap;
		
		protected var parentContainer:Container;
		
		protected var maskSet:Boolean = false;
		protected var isFloating:Boolean = false;
		
		protected var contentFixed:Array = new Array(0);
		protected var contentFloat:Array = new Array(0);
		
		// ======== Constructor ======== 
		
		public function Container(Name:String, Width:Number = 0, Height:Number = 0) {
			name = Name;
			
			framesLayer = new Sprite();
			fixedLayer = new Sprite();
			floatingLayer = new Sprite();
			background = new Sprite();
			
			addChild(background);
			background.visible = false;
			
			addChild(fixedLayer);
			fixedLayer.visible = true;
			
			addChild(floatingLayer);
			floatingLayer.visible = true;
			
			addChild(framesLayer);
			framesLayer.visible = false;
			
			setSize(Width, Height);
			
			if (size.x * size.y > 0 ) {
				updateMask();
			}
		}
		
		public function setSize(Width:Number, Height:Number):void {
			size = new Point(Width, Height);
			if (Width * Height > 0) sizeSet = true;
			else sizeSet = false;
			updateContent();
			update();
		}
		
		public function update():void {
			updateFixed();
			updateBackground();
			updateFloat();
			updateFrames();
			// if (parentContainer != null) parentContainer.update();
		}
		
		public function updateContent():void {
			trace("updateContent", this.toString(), "("+parentContainer+")");
			for (var i:int = 0; i < contentFixed.length ; i++) {
				contentFixed[i].updateContent();
			}
			update();
		}
		
		// ======== Contents ========
		
		public function add(newContent:*, Floating:Boolean = false):void {
			// TODO: Add sprite, bitmap, displayobject...
			if ( (newContent is Gadget || newContent is Container) == false ) throw Error("Content must be of type Gadget or Container");
			
			newContent.makeChild(this, Floating);
			if (Floating) {
				newContent.addEventListener(MouseEvent.MOUSE_DOWN, floatOnTop);
				contentFloat.push(newContent);
				updateFloat();
			} else {
				contentFixed.push(newContent);
				if (sizeSet == false) update();
				else updateFixed();
			}
		}
		
		public function updateFixed():void {
			if (sizeSet == false) {
				size.x = 0;
				size.y = 0;
			}
			
			for (var i:int = 0; i < contentFixed.length; i++) {
				fixedLayer.addChild( contentFixed[i] );
				
				if (sizeSet == false) {
					size.x = Math.max(size.x, contentFixed[i].x + contentFixed[i].width + padding.left + padding.right);
					size.y = Math.max(size.y, contentFixed[i].y + contentFixed[i].height + padding.top + padding.bottom);
				}
			}
			
			fixedLayer.x = padding.left;
			fixedLayer.y = padding.top;
		}
		
		public function updateFloat():void {
			for (var i:int = 0; i < contentFloat.length; i++) {
				floatingLayer.addChild( contentFloat[i] );
			}
		}
		
		public function makeChild(ofContainer:Container, IsFloating:Boolean = false):void {
			parentContainer = ofContainer as Container;
			isFloating = IsFloating;
		}
		
		protected function floatOnTop(e:MouseEvent):void {
			floatingLayer.setChildIndex(e.currentTarget as DisplayObject, floatingLayer.numChildren - 1);
		}
		
		public function setContentPadding(horizontal:Number, vertical:Number):void {
			var diffX:Number = horizontal - contentPadding.x;
			var diffY:Number = vertical - contentPadding.y;
			
			for (var i:int = 0; i < contentFixed.length ; i++) {
				contentFixed[i].x += diffX + padding.x;
				contentFixed[i].y += diffY + padding.y;
			}
			contentPadding.x = horizontal;
			contentPadding.y = vertical;
			
			updateFixed();
		}
		
		public function setAlignments(AlignHorizontal:String, AlignVertical:String):void {
			alignHorizontal = AlignHorizontal;
			alignVertical = AlignVertical;
		}
		
		// ======== Mask ========
		
		public function setMask(newMask:*):void {
			mask = newMask;
			if (mask != null) maskSet = true;
			else maskSet = false;
		}
		
		public function updateMask():void {
			if (maskSet == false) {
				if (mask == null) mask = Util.buildMask(0, 0, size.x, size.y);
				addChild(mask);
			}
		}
		
		// ======== Style ========
		
		public function setStyle(newStyle:StyleContainer):void {
			style = newStyle;
			updateFromStyle();
		}
		
		public function updateFromStyle():void {
			setBackground(style.background, style.backgroundMode);
			setFrames(style);
			padding = style.padding;
			
			updateBackground();
			updateFrames();
		}
		
		// ======== Background ========
		
		public function setBackground(newBackground:* = null, mode:String = null, backgroundAlpha:Number = 1):void {
			if (newBackground is Sprite) background = newBackground.clone();
			else if (newBackground is Bitmap) background = new Bitmap(newBackground.bitmapData);
			else if (newBackground is BitmapData) background = new Bitmap(newBackground);
			else if (newBackground != null) throw Error("Background must be Bitmap, BitmapData or Sprite");
			
			if (newBackground != null) {
				addChildAt(background, 0);
				background.visible = true;
			}
			
			background.visible = true;
			background.alpha = backgroundAlpha;
			if (mode != null) backgroundMode = mode;
			
			updateBackground();
		}
		
		public function updateBackground(newMode:String = null):void {
			if (newMode != null) backgroundMode = newMode;
			switch(backgroundMode) {
				case UIConst.GRAPHICS_FIXED:
					background.scaleX = 1;
					background.scaleY = 1;
					background.x = 0;
					background.y = 0;
					break;
				case UIConst.GRAPHICS_CENTER:
					background.scaleX = 1;
					background.scaleY = 1;
					background.x = (width - background.width) / 2;
					background.y = (height - background.height) / 2;	
					break;
				case UIConst.GRAPHICS_STRETCH:
					background.width = width;
					background.height = height;
					background.x = 0;
					background.y = 0;
					break;
				case UIConst.GRAPHICS_INFRAME:
					// TODO: Container UIConst.INFRAME
					break;
				case UIConst.GRAPHICS_GADGET:
					// TODO: Container UIConst.GADGET
					break;
			}
		}
		
		// ======== Frames ======== 
		
		public function setFrames(fromStyle:StyleContainer):void {
			frameMode = fromStyle.frameMode;
			hasSides = fromStyle.hasSides;
			hasCorners = fromStyle.hasCorners;
			
			if (hasSides) {
				sideLeft = new Bitmap(fromStyle.sideLeft);
				sideRight = new Bitmap(fromStyle.sideRight);
				sideTop = new Bitmap(fromStyle.sideTop);
				sideBottom = new Bitmap(fromStyle.sideBottom);
				
				framesLayer.addChild(sideLeft);
				framesLayer.addChild(sideRight);
				framesLayer.addChild(sideTop);
				framesLayer.addChild(sideBottom);
			}
			
			if (hasCorners) {
				cornerTopLeft = new Bitmap(fromStyle.cornerTopLeft);
				cornerTopRight = new Bitmap(fromStyle.cornerTopRight);
				cornerBottomLeft = new Bitmap(fromStyle.cornerBottomLeft);
				cornerBottomRight = new Bitmap(fromStyle.cornerBottomRight);
				
				framesLayer.addChild(cornerTopLeft);
				framesLayer.addChild(cornerTopRight);
				framesLayer.addChild(cornerBottomLeft);
				framesLayer.addChild(cornerBottomRight);
			}
			
			framesLayer.visible = true;
			
			updateFrames();
		}
		
		public function updateFrames():void {
			
			if (frameMode == UIConst.FRAMES_SIDES_ONLY || frameMode == UIConst.FRAMES_CORNERS_ON_TOP ) {
				sideLeft.x = 0;
				sideLeft.y = 0;
				sideLeft.height = height;
				
				sideRight.x = width - width;
				sideRight.y = 0;
				sideRight.height = height;
				
				sideTop.x = 0;
				sideTop.y = 0;
				sideTop.width = width;
				
				sideBottom.x = 0;
				sideBottom.y = height - height;
				sideBottom.width = width;
			}
			
			if (frameMode == UIConst.FRAMES_CORNERS_ONLY || frameMode == UIConst.FRAMES_CORNERS_ON_TOP ) {
				cornerTopLeft.x = 0;
				cornerTopLeft.y = 0;
				
				cornerTopRight.x = width - cornerTopRight.width;
				cornerTopRight.y = 0;
				
				cornerBottomLeft.x = 0;
				cornerBottomLeft.y = height - cornerBottomLeft.height;
				
				cornerBottomRight.x = width - cornerBottomRight.width;
				cornerBottomRight.y = height - cornerBottomRight.height;
			}
			
			if (frameMode == UIConst.FRAMES_SIDES_BETWEEN_CORNERS) {
				cornerTopLeft.x = 0;
				cornerTopLeft.y = 0;
				
				cornerTopRight.x = width - cornerTopRight.width;
				cornerTopRight.y = 0;
				
				cornerBottomLeft.x = 0;
				cornerBottomLeft.y = height - cornerBottomLeft.height;
				
				cornerBottomRight.x = width - cornerBottomRight.width;
				cornerBottomRight.y = height - cornerBottomRight.height;
				
				sideLeft.x = 0;
				sideLeft.y = cornerTopLeft.height;
				sideLeft.height = height - cornerTopLeft.height - cornerBottomLeft.height;
				
				sideRight.x = width - sideRight.width;
				sideRight.y = cornerTopRight.height;
				sideRight.height = height - cornerTopRight.height - cornerBottomRight.height;
				
				sideTop.x = cornerTopLeft.width;
				sideTop.y = 0;
				sideTop.width = width - cornerTopLeft.width - cornerTopRight.width;
				
				sideBottom.x = cornerBottomLeft.width;
				sideBottom.y = height - sideBottom.height;
				sideBottom.width = width - cornerBottomLeft.width - cornerBottomRight.width;;
			}
		}
		
		// ======== Misc ======== 
		
		protected function isBgMode(value:String):Boolean {
			if (value == UIConst.GRAPHICS_FIXED) return true;
			if (value == UIConst.GRAPHICS_CENTER) return true;
			if (value == UIConst.GRAPHICS_STRETCH) return true;
			if (value == UIConst.GRAPHICS_INFRAME) return true;
			if (value == UIConst.GRAPHICS_GADGET) return true;
			return false;
		}
		
		protected function isFrMode(value:String):Boolean {
			if (value == UIConst.FRAMES_SIDES_ONLY) return true;
			if (value == UIConst.FRAMES_CORNERS_ONLY) return true;
			if (value == UIConst.FRAMES_SIDES_BETWEEN_CORNERS) return true;
			if (value == UIConst.FRAMES_CORNERS_ON_TOP) return true;
			return false;
		}
		
		// ========= Getters & Setters ========
		
		override public function get width():Number {
			return size.x;
		}
		
		override public function get height():Number {
			return size.y;
		}
		
		override public function set width(value:Number):void {
			setSize(value, height);
		}
		
		override public function set height(value:Number):void {
			setSize(width, value);
		}
		
		public function get alignVertical():String { return _alignVertical; }
		
		public function set alignVertical(value:String):void {
			_alignVertical = value.toLowerCase();
		}
		
		public function get alignHorizontal():String { return _alignHorizontal; }
		
		public function set alignHorizontal(value:String):void {
			_alignHorizontal = value.toLowerCase();
		}
		
	}

}